﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using BenevolentSunData;

namespace BenevolentSun
{
    public class Sprite
    {

        private Texture2D texture = null;
        public Texture2D Texture
        {
            get { return texture; }
            set { texture = value; if (texture == null) nineSlice = null; } 
        }

        public Vector2 Scale = Vector2.One;

        public Vector2 Position = Vector2.Zero;

        /// <summary>
        /// Angle of rotation in degrees around the origin.
        /// </summary>
        public float Rotation = 0f;

        /// <summary>
        /// The origin of the texture with the coordinate system top left aligned.
        /// </summary>
        public Vector2 Origin = Vector2.Zero;
        public void CalcOrigin(float pctX, float pctY)
        {
            Origin.X = pctX * Texture.Width;
            Origin.Y = pctY * Texture.Height;
        }


        public float LayerDepth = 0f;

        public SpriteEffects SpriteEffects = SpriteEffects.None;

        public Color Color = Color.White;

        /// <summary>
        /// A portion of the texture should be used, if specified the texture will be rendered as if it is only this portion.
        /// </summary>
        private Rectangle? sourceRectangle = null;
        public Rectangle? SourceRectangle
        {
            get { return sourceRectangle; }
            set
            {
                if (nineSlice != null && (value.Value.Width < nineSlice.Value.Width || value.Value.Height < nineSlice.Value.Height))
                    throw (new Exception("Invalid source rect, there is already a nine slice that is greater than this source rect!"));
                sourceRectangle = value;
            }
        }


        public Vector2 TextureDimension
        {
            get 
            {
                if (Texture != null)
                    return new Vector2(Texture.Width, Texture.Height);
                else
                    return Vector2.Zero;
            }
        }


        public Sprite(Texture2D texture)
        {
            Texture = texture;
        }


        private Rectangle? nineSlice = null;
        public Rectangle? NineSlice
        {
            get { return nineSlice; }
            set {
                if (Texture == null)
                    throw (new Exception("Cannot set nine slice when texture is null!"));
                if (value.Value.X < 0 || value.Value.Y < 0 || value.Value.Width < 0 || value.Value.Height < 0 || value.Value.Right > Texture.Width || value.Value.Bottom > Texture.Height)
                    throw (new Exception("Invalid nine slice dimensions, the center nine slice rect must fit inside of the texture and cannot have negative bounds!"));
                if (SourceRectangle != null && (value.Value.Width > SourceRectangle.Value.Width || value.Value.Height > SourceRectangle.Value.Height))
                    throw (new Exception("Invalid nine slice dimensions, the center nine slice rect must fit inside of the source rectangle!"));
                nineSlice = value; 
            }
        }


        public void Draw(SpriteBatch spriteBatch)
        {
            if (Texture != null)
            {
                if (NineSlice == null)
                {
                    spriteBatch.Draw(Texture, Position, SourceRectangle, Color, Rotation, Origin, Scale, SpriteEffects, LayerDepth);
                }
                else
                {
                    Rectangle topLeft = new Rectangle(0, 0, NineSlice.Value.Left, NineSlice.Value.Top);
                    Rectangle left = new Rectangle(0, NineSlice.Value.Top, NineSlice.Value.Left, NineSlice.Value.Height);
                    Rectangle bottomLeft = new Rectangle(0, NineSlice.Value.Bottom, NineSlice.Value.Left, Texture.Height - NineSlice.Value.Bottom);

                    Rectangle topCenter = new Rectangle(NineSlice.Value.Left, 0, NineSlice.Value.Width, NineSlice.Value.Top);
                    Rectangle center = new Rectangle(NineSlice.Value.Left, NineSlice.Value.Top, NineSlice.Value.Width, NineSlice.Value.Height);
                    Rectangle bottomCenter = new Rectangle(NineSlice.Value.Left, NineSlice.Value.Bottom, NineSlice.Value.Width, Texture.Height - NineSlice.Value.Bottom);

                    Rectangle topRight = new Rectangle(NineSlice.Value.Right, 0, Texture.Width - NineSlice.Value.Right, NineSlice.Value.Top);
                    Rectangle right = new Rectangle(NineSlice.Value.Right, NineSlice.Value.Top, Texture.Width - NineSlice.Value.Right, NineSlice.Value.Height);
                    Rectangle bottomRight = new Rectangle(NineSlice.Value.Right, NineSlice.Value.Bottom, Texture.Width - NineSlice.Value.Right, Texture.Height - NineSlice.Value.Bottom);

                    if (SourceRectangle != null)
                    {
                        topLeft.Offset(sourceRectangle.Value.X, sourceRectangle.Value.Y);
                        left.Offset(sourceRectangle.Value.X, sourceRectangle.Value.Y);
                        bottomLeft.Offset(sourceRectangle.Value.X, sourceRectangle.Value.Y);

                        topCenter.Offset(sourceRectangle.Value.X, sourceRectangle.Value.Y);
                        center.Offset(sourceRectangle.Value.X, sourceRectangle.Value.Y);
                        bottomCenter.Offset(sourceRectangle.Value.X, sourceRectangle.Value.Y);

                        topRight.Offset(sourceRectangle.Value.X, sourceRectangle.Value.Y);
                        right.Offset(sourceRectangle.Value.X, sourceRectangle.Value.Y);
                        bottomRight.Offset(sourceRectangle.Value.X, sourceRectangle.Value.Y);
                    }

                    Vector2 centerScale = new Vector2();
                    centerScale.X = (((Texture.Width * Scale.X) - topLeft.Width - topRight.Width) / (Scale.X * topCenter.Width)) * Scale.X;
                    centerScale.Y = (((Texture.Height * Scale.Y) - topLeft.Height - bottomLeft.Height) / (Scale.Y * left.Height)) * Scale.Y;

                    if (!topLeft.IsEmpty) spriteBatch.Draw(Texture, Position +      new Vector2(topLeft.X,      topLeft.Y), topLeft, Color, Rotation, Origin, new Vector2(1, 1), SpriteEffects, LayerDepth);
                    if (!left.IsEmpty) spriteBatch.Draw(Texture, Position + new Vector2(left.X, left.Y), left, Color, Rotation, Origin, new Vector2(1, centerScale.Y), SpriteEffects, LayerDepth);
                    if (!bottomLeft.IsEmpty) spriteBatch.Draw(Texture, Position + new Vector2(bottomLeft.X, topLeft.Height + left.Height * centerScale.Y), bottomLeft, Color, Rotation, Origin, new Vector2(1, 1), SpriteEffects, LayerDepth);

                    if (!topCenter.IsEmpty) spriteBatch.Draw(Texture, Position + new Vector2(topCenter.X, topCenter.Y), topCenter, Color, Rotation, Origin, new Vector2(centerScale.X, 1), SpriteEffects, LayerDepth);
                    if (!center.IsEmpty) spriteBatch.Draw(Texture, Position + new Vector2(center.X, center.Y), center, Color, Rotation, Origin, centerScale, SpriteEffects, LayerDepth);
                    if (!bottomCenter.IsEmpty) spriteBatch.Draw(Texture, Position + new Vector2(bottomCenter.X, topLeft.Height + left.Height * centerScale.Y), bottomCenter, Color, Rotation, Origin, new Vector2(centerScale.X, 1), SpriteEffects, LayerDepth);

                    if (!topRight.IsEmpty) spriteBatch.Draw(Texture, Position + new Vector2(topLeft.Width + topCenter.Width * centerScale.X, topRight.Y), topRight, Color, Rotation, Origin, new Vector2(1, 1), SpriteEffects, LayerDepth);
                    if (!right.IsEmpty) spriteBatch.Draw(Texture, Position + new Vector2(topLeft.Width + topCenter.Width * centerScale.X, right.Y), right, Color, Rotation, Origin, new Vector2(1, centerScale.Y), SpriteEffects, LayerDepth);
                    if (!bottomRight.IsEmpty) spriteBatch.Draw(Texture, Position + new Vector2(topLeft.Width + topCenter.Width * centerScale.X, topLeft.Height + left.Height * centerScale.Y), bottomRight, Color, Rotation, Origin, new Vector2(1, 1), SpriteEffects, LayerDepth);
                }
            }
        }

    }
}
